package luminus.origin.commands

import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.InventoryCloseEvent
import taboolib.common.platform.event.SubscribeEvent
import taboolib.common.platform.function.submit

import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.inventory.Inventory
import taboolib.common.platform.command.*
import taboolib.platform.util.sendLang

@CommandHeader(name = "invsee", permission = "luminus.invsee", aliases = ["inventorysee"], permissionDefault = PermissionDefault.OP)
object Invsee {
    private val viewingInventories = mutableMapOf<Player, Pair<Player, Inventory>>()

    @CommandBody
    val main = mainCommand {
        execute<Player> { sender, _, _ ->
            sender.sendLang("commands-invsee-usage")
        }
        dynamic("player") {
            suggest { Bukkit.getOnlinePlayers().map { it.name } }
            execute<Player> { sender, _, argument ->
                val target = Bukkit.getPlayer(argument) ?: run {
                    sender.sendLang("commands-invsee-player-not-found", argument)
                    return@execute
                }

                if (sender == target) {
                    sender.sendLang("commands-invsee-self")
                    return@execute
                }

                openInventoryViewer(sender, target)
            }
        }
        literal("reload", permission = "luminus.reload") {
            execute<Player> { sender, _, _ ->
                viewingInventories.keys.toList().forEach { it.closeInventory() }
                viewingInventories.clear()
                sender.sendLang("commands-invsee-reloaded")
            }
        }
    }
    private fun openInventoryViewer(viewer: Player, target: Player) {
        val inventory = Bukkit.createInventory(
            null,
            45,
            "§e${target.name} 的物品栏"
        ).apply {
            contents = target.inventory.contents.clone()
            setItem(36, target.inventory.helmet)
            setItem(37, target.inventory.chestplate)
            setItem(38, target.inventory.leggings)
            setItem(39, target.inventory.boots)
            setItem(40, target.inventory.itemInOffHand)
            for (i in 0..8) {
                setItem(41 + i, target.inventory.getItem(i))
            }
        }
        viewer.openInventory(inventory)
        viewingInventories[viewer] = target to inventory

        viewer.sendLang("commands-invsee-opened", target.name)
    }

    private fun syncInventoryChanges(viewer: Player) {
        val (target, inventory) = viewingInventories[viewer] ?: return
        for (i in 0..35) {
            target.inventory.setItem(i, inventory.getItem(i))
        }
        target.inventory.helmet = inventory.getItem(36)
        target.inventory.chestplate = inventory.getItem(37)
        target.inventory.leggings = inventory.getItem(38)
        target.inventory.boots = inventory.getItem(39)
        target.inventory.setItemInOffHand(inventory.getItem(40))

    }

    @SubscribeEvent
    fun onInventoryClose(event: InventoryCloseEvent) {
        val player = event.player as? Player ?: return
        viewingInventories.remove(player)?.let {
            player.sendLang("commands-invsee-closed", it.first.name)
        }
    }

    @SubscribeEvent
    fun onInventoryClick(event: InventoryClickEvent) {
        val viewer = event.whoClicked as? Player ?: return
        if (viewingInventories.containsKey(viewer)) {
            if (event.rawSlot in 41..44) {
                event.isCancelled = true
                return
            }
            submit(delay = 1L) {
                syncInventoryChanges(viewer)
            }
        }
    }
}